<?php
namespace frame;
/**
 * framePHP内置模板引擎类
 * 支持XML标签和普通标签的模板解析
 * 编译型模板引擎 支持动态缓存
 */
class  Template{
	
    public      $tVar            =   array();// 模板变量
    public      $config          =   array();// 配置信息

      /**
     * 架构函数
     * @access public
     */
    public function __construct(){
        $this->config['cache_path']         =   C('CACHE_PATH');//应用模板缓存目录
        $this->config['cache_suffix']       =   C('TMPL_CACHFILE_SUFFIX');// 默认模板缓存后缀
        $this->config['tmpl_begin']         =   $this->stripPreg(C('TMPL_L_DELIM'));// 模板引擎普通标签开始标记
        $this->config['tmpl_end']           =   $this->stripPreg(C('TMPL_R_DELIM'));// 模板引擎普通标签结束标记
    }

    //符号转义
    private function stripPreg($str) {
        return str_replace(
            array('{','}','(',')','|','[',']','-','+','*','.','^','?'),
            array('\{','\}','\(','\)','\|','\[','\]','\-','\+','\*','\.','\^','\?'),
            $str);        
    }    

	 /**
     * 加载模板
     * @access public
     * @param string $templateFile 模板文件
     * @param array  $templateVar 模板变量
     * @param string $prefix 模板标识前缀
     * @return void
     */
    public function fetch($templateFile,$templateVar,$prefix='') {
        $this->tVar         =   $templateVar;
        $templateCacheFile  =   $this->loadTemplate($templateFile,$prefix);
        Storage::load($templateCacheFile,$this->tVar,null,'tpl');
    }

    /**
     * 加载主模板并缓存
     * @access public
     * @param string $templateFile 模板文件
     * @param string $prefix 模板标识前缀
     * @return string
     * @throws ThinkExecption
     */
    public function loadTemplate($templateFile,$prefix='') {
        if(is_file($templateFile)) {
            $this->templateFile    =  $templateFile;
            // 读取模板文件内容
            $tmplContent =  file_get_contents($templateFile);
        }
       
        // 根据模版文件名定位缓存文件
        $tmplCacheFile = $this->config['cache_path'].$prefix.md5($templateFile).$this->config['cache_suffix'];
        // 编译模板内容
        $tmplContent =  $this->compiler($tmplContent);
        //文件写入
        Storage::put($tmplCacheFile,trim($tmplContent),'tpl');
        return $tmplCacheFile;
    }

    /**
     * 编译模板文件内容
     * @access protected
     * @param mixed $tmplContent 模板内容
     * @return string
     */
    protected function compiler($tmplContent){
        //模板解析
        $tmplContent =  $this->parse($tmplContent);
        return strip_whitespace($tmplContent);
    }

      /**
     * 模板解析入口
     * 支持普通标签和TagLib解析 支持自定义标签库
     * @access public
     * @param string $content 要解析的模板内容
     * @return string
     */
    public function parse($content){
        //1.内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀
        // $tagLibs =  explode(',',C('TAGLIB_BUILD_IN'));
        // foreach ($tagLibs as $tag){
        //     $this->parseTagLib($tag,$content,true);
        // }
        //2.解析普通模板标签 {$tagName}
        $reg = '/('.$this->config['tmpl_begin'].')([^\d\w\s'.$this->config['tmpl_begin'].$this->config['tmpl_end'].'].+?)('.$this->config['tmpl_end'].')/is';
        //i 不区分大小写
        //s 模式中的圆点元字符（.）匹配所有的字符，包括换行符
        $content = preg_replace_callback($reg, array($this, 'parseTag'),$content);
        return $content;
    }

      /**
     * 模板标签解析
     * 格式： {TagName:args [|content] }
     * @access public
     * @param string $tagStr 标签内容
     * @return string
     */
    public function parseTag($tagStr){
         dump($tagStr);    
        if(is_array($tagStr)) $tagStr = $tagStr[2];
        $tagStr = stripslashes($tagStr);//删除反斜杠
        $flag   =  substr($tagStr,0,1);
        $flag2  =  substr($tagStr,1,1);
        $name   = substr($tagStr,1);
        if('$' == $flag && '.' != $flag2 && '(' != $flag2){ //解析模板变量 格式 {$varName}
            return $this->parseVar($name);    
        }elseif('-' == $flag || '+'== $flag){ // 输出计算
            return  '<?php echo '.$flag.$name.';?>';
        }        
    }

    /**
     * 模板变量解析,支持使用函数
     * 格式： {$varname|function1|function2=arg1,arg2}
     * @access public
     * @param string $varStr 变量数据
     * @return string
     */
    public function parseVar($varStr){
        $varStr     =   trim($varStr);
        static $_varParseList = array();
        //如果已经解析过该变量字串，则直接返回变量值
        if(isset($_varParseList[$varStr])) return $_varParseList[$varStr];
        $parseStr   =   '';
        $varExists  =   true;
        if(!empty($varStr)){
            $varArray = explode('|',$varStr);
            //取得变量名称
            $var = array_shift($varArray);
            $name = "$$var";
            $parseStr = '<?php echo ('.$name.'); ?>';
        }
        $_varParseList[$varStr] = $parseStr;
        return $parseStr;
    }    

}